package pers.mihao.ancient_empire.startup.config.aspect;


import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.ProxyMethodInvocation;
import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint;
import org.springframework.stereotype.Component;
import pers.mihao.ancient_empire.auth.util.LoginUserHolder;
import pers.mihao.ancient_empire.common.annotation.ValidatedBean;
import pers.mihao.ancient_empire.common.annotation.redis.NotGenerator;
import pers.mihao.ancient_empire.common.dto.ApiPageDTO;
import pers.mihao.ancient_empire.common.dto.ApiRequestDTO;
import pers.mihao.ancient_empire.common.util.ReflectUtil;
import pers.mihao.ancient_empire.common.util.ValidateUtil;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Method;

/**
 * 验证参数 设置信息 aop
 *
 * @author hspcadmin
 */
@Component
@Aspect
public class ControllerFilterAspect {

    Logger log = LoggerFactory.getLogger(ControllerFilterAspect.class);


    @Pointcut("execution(public * pers.mihao.ancient_empire..*Controller.*(..))")
    public void AllController() {
    }

    @Around("AllController()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        if (joinPoint instanceof MethodInvocationProceedingJoinPoint) {
            MethodInvocationProceedingJoinPoint point = (MethodInvocationProceedingJoinPoint) joinPoint;
            ProxyMethodInvocation proxyMethodInvocation = (ProxyMethodInvocation)
                    ReflectUtil.getValueByFieldName(point, "methodInvocation");
            Method method = proxyMethodInvocation.getMethod();
            Object[] args = point.getArgs();
            // 补充参数
            setParameter(args);
            // 验证参数
            verificationParameters(point.getTarget().getClass(), method, args);
        }
        return joinPoint.proceed();
    }

    /**
     * 补充参数
     *
     * @param args
     */
    private void setParameter(Object[] args) {

        ApiPageDTO apiPageDTO;
        ApiRequestDTO apiRequestDTO;
        Integer pageSize, pageStart, limitStart;

        for (Object arg : args) {
            if (arg instanceof ApiPageDTO) {
                apiPageDTO = (ApiPageDTO) arg;
                pageSize = apiPageDTO.getPageSize();
                pageStart = apiPageDTO.getPageStart();
                apiPageDTO.setLimitStart((pageStart - 1) * pageSize);
                apiPageDTO.setLimitCount(pageSize);
                apiPageDTO.setUserId(LoginUserHolder.getUserId());
            } else if (arg instanceof ApiRequestDTO) {
                apiRequestDTO = (ApiRequestDTO) arg;
                apiRequestDTO.setUserId(LoginUserHolder.getUserId());
            }
        }
    }

    /**
     * 验证参数
     * 基础类型根据注解判断是否校验
     * 自定义对象根据包名判断是否校验
     *
     * @param args
     */
    private void verificationParameters(Class clazz, Method method, Object[] args) {
        if (clazz.getAnnotation(NotGenerator.class) != null) {
            return;
        }
        if (method.getAnnotation(NotGenerator.class) != null) {
            return;
        }
        ValidateUtil.validate(clazz, method, args);
    }
}
